﻿
namespace Edu.Technion.CSE.OpenUnit4.CollectionsLib
{
    /// <summary>
    /// 
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public class List<T> : IList<T>
    {
        // Members

        /// <summary>
        /// 
        /// </summary>
        private Node<T> first;

        // Constructors

        /// <summary>
        /// 
        /// </summary>
        public List()
        {
            this.first = null;
        }

        // Public Methods

        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        public Node<T> GetFirst()
        {
            return this.first;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="pos"></param>
        /// <param name="newItem"></param>
        /// <returns></returns>
        public Node<T> Insert(Node<T> pos, T newItem)
        {
            Node<T> newNode = new Node<T>(newItem);

            // Check if the position is as the first node
            if (pos == null)
            {
                // Add the new node as the first node in the list
                newNode.SetNext(first);
                first = newNode;
            }
            else
            {
                // If the position is not the first node, add it, and set the "next" fields as required
                newNode.SetNext(pos.GetNext());
                pos.SetNext(newNode);
            }

            // Return a reference to the new added node
            return newNode;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        public bool IsEmpty()
        {
            return (first == null);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="pos"></param>
        /// <returns></returns>
        public Node<T> Remove(Node<T> pos)
        {
            Node<T> currentNode = GetFirst();
            // In case the required node to remove - is the first one
            if (currentNode == pos)
            {
                // Point "first" to the next (second node, or null if list contains only one node) node
                first = pos.GetNext();
            }
            else // The node is not the first one
            {
                // find the position of the node right before the required node                
                while (currentNode.GetNext() != pos)
                {
                    currentNode = currentNode.GetNext();
                }
                // Point the "next" of the node before the required one - to skip it
                currentNode.SetNext(pos.GetNext());
            }

            // Disconnect the required node from the list (i.e. set it's "next" to null)
            pos.SetNext(null);

            // Return a reference to the next node, after the required one.
            return currentNode.GetNext();
        }

        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        public override string ToString()
        {
            // Open Brackets
            System.Text.StringBuilder sb = new System.Text.StringBuilder("[");

            // Build the strings of nodes
            for (Node<T> node = this.first; node != null; node = node.GetNext())
            {
                // Add the node's content, and if the are more node - add comma as well
                sb.Append(node.GetInfo().ToString());
                if (node.GetNext() != null)
                {
                    sb.Append(",");
                }
            }
            // Close Brackets
            sb.Append("]");
            return sb.ToString();
        }
    }
}
